package com.zhh.service.impl;

import com.zhh.common.IDUtil;
import com.zhh.common.ResponseCode;
import com.zhh.common.ServerResponse;
import com.zhh.dao.*;
import com.zhh.dto.EncaseOrderDto;
import com.zhh.dto.FacilityDto;
import com.zhh.dto.MedicineDto;
import com.zhh.pojo.*;
import com.zhh.service.OrderService;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.*;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private FacilityLeaseDao leaseDao;

    @Autowired
    private FacilityDao facilityDao;

    @Autowired
    private OrderItemDao itemDao;

    @Autowired
    private MedicineDao medicineDao;

    @Autowired
    private OrderRejectDao rejectDao;

    @Autowired
    private OrderOtherDao orderOtherDao;

    @Autowired
    private OrderShippingDao shippingDao;

    @Override
    public ServerResponse getOrderList(String orderId, Integer state,int pageSize,int pageNum) {
        TbOrder order = new TbOrder();
        if (!StringUtils.isBlank(orderId)){
            order.setOrderId(orderId);
        }
        if (state!=null){
            order.setStatus(state);
        }
        Example<TbOrder> example = Example.of(order);
        Pageable pageable = PageRequest.of(pageNum-1,pageSize);
        Page<TbOrder> orderList = orderDao.findAll(example,pageable);
//        orderDao.fi
        List<EncaseOrderDto> list = new ArrayList<>();
        if (orderList.getContent()!=null && orderList.getSize()>0){
            for (TbOrder o:orderList.getContent()){
                EncaseOrderDto dto = new EncaseOrderDto();
                List<FacilityDto> flist = new ArrayList<>();
                List<MedicineDto> medicineDtoList = new ArrayList<>();
                List<TbOrderItem> mlist = itemDao.findByOrderId(o.getOrderId());
                List<TbFacilityLease> leases = leaseDao.findByOrderIdAndStateGreaterThanEqual(o.getOrderId(),0);
                if (leases!=null){
                    for (TbFacilityLease l:leases){
                        if (l.getFacilityId() !=null){
                            Optional<TbFacility> op  = facilityDao.findById(l.getFacilityId());
                            op.ifPresent(facility -> flist.add(facility2Dto(facility)));
                        }
                    }
                }
                if (mlist !=null){
                    for (TbOrderItem i:mlist){
                        if (!StringUtils.isBlank(i.getItemId())){
                            Optional<TbMedicine> m = medicineDao.findById(Integer.parseInt(i.getItemId()));
                            m.ifPresent(medicine -> medicineDtoList.add(medicine2Dto(medicine)));
                        }
                    }
                }
                dto.setOrderSuid(o.getOrderId());
                if (o.getDispenserId() !=null){
                    dto.setHandlerId(o.getDispenserId());
                    Optional<TbUser> dip = userDao.findById(o.getDispenserId());
                    dip.ifPresent(user-> dto.setHandlerName(user.getUsername()));
                }
                dto.setCargos(medicineDtoList);
                dto.setFacility(flist);
                dto.setCreateTime(o.getCreateTime());
                dto.setReserveTime(o.getReserveTime());
                list.add(dto);
            }
        }
        Page<EncaseOrderDto> result = new PageImpl<>(list,pageable,orderList.getTotalElements());

        return ServerResponse.createBySuccess(result);
    }

    @Override
    @Transactional
    public ServerResponse encaseOrder(String orderId) {
        TbUser user = getUser();
        Optional<TbOrder> op = orderDao.findById(orderId);
        if (!op.isPresent()){
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),"订单参数错误");
        }
        TbOrder order = op.get();
        if (order.getDispenserId() !=null || order.getStatus() >=20){
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),"慢一步,订单已被领取");
        }
        if (order.getStatus()<10){
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),"订单未确认");
        }
        orderDao.updateOrder(orderId,15,user.getId());
        return  ServerResponse.createBySuccessMessage("领取订单成功");
    }

    @Override
    @Transactional
    public ServerResponse pushOrder(EncaseOrderDto dto) {
        TbUser user = getUser();
        if (StringUtils.isBlank(dto.getOrderSuid())){
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),"订单参数错误,订单号不能为空");
        }
        Optional<TbOrder> op = orderDao.findById(dto.getOrderSuid());
        if (!op.isPresent()){
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),"订单参数错误");
        }
        TbOrder order = op.get();
        if (!user.getId().equals(order.getDispenserId())){
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),"参数错误,不是您的订单,您无法提交复核");
        }

        List<FacilityDto> facilityDtos = dto.getFacility();
        List<MedicineDto> medicineDtoList = dto.getCargos();

        if (facilityDtos !=null && facilityDtos.size()>0){
            for (FacilityDto d:facilityDtos){
                if (StringUtils.isBlank(d.getSuid())){
                    continue;
                }
                // 物资是否存在
                TbFacility facility = facilityDao.findTbFacilityBySuidEquals(d.getSuid());
                if (facility ==null){
                    continue;
                }
                // 判断物资有没有被占用
                TbFacilityLease lease = leaseDao.findTopByFacilityIdAndState(facility.getId(),0);
                if (lease!=null ||facility.getState() !=0){
                    return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),"物资"+facility.getSuid()+"已被使用,无法被领取");
                }
                //如果是冰块,需要比较冷冻时间
                if (facility.getType()==1000){
                    TbFacilityLease l2 = leaseDao.findTopByFacilityIdAndState(facility.getId(),10);
                    if (new Date().getTime() - l2.getStorageTime().getTime() < facility.getCooldown()*60*60*1000){
                        return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),"冰块"+facility.getSuid()+"还未达到领取时间");
                    }
                }
                // 新增物资使用记录
                TbFacilityLease l = new TbFacilityLease();
                l.setUserId(user.getId());
                l.setId(UUID.randomUUID().toString());
                l.setFacilityId(facility.getId());
                l.setOrderId(order.getOrderId());
                l.setState(0);
                leaseDao.save(l);
            }
        }
        if (medicineDtoList !=null && medicineDtoList.size()>0){
            for (MedicineDto m:medicineDtoList){
                if (StringUtils.isBlank(m.getSelfcode())){
                    continue;
                }
                TbMedicine medicine=  medicineDao.findBySelfcode(m.getSelfcode());
                if (medicine==null){
                    continue;
                }
                TbOrderItem item = new TbOrderItem();
                item.setItemId(Integer.toString(medicine.getMedicineId()));
                item.setOrderId(order.getOrderId());
                item.setNum(m.getNum());
                item.setId(IDUtil.getRandomIdStr());
                itemDao.save(item);
            }
        }
        orderDao.updateOrder(order.getOrderId(),18,user.getId());
        return  ServerResponse.createBySuccessMessage("提交复核成功");
    }

    @Override
    @Transactional
    public ServerResponse cancelOrder(String orderId) {
        TbUser user = getUser();
        Optional<TbOrder> op = orderDao.findById(orderId);
        if (!op.isPresent()){
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),"订单参数错误");
        }
        TbOrder order = op.get();
        if (!user.getId().equals(order.getDispenserId())){
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),"参数错误,不是您的订单,您无法取消");
        }
        orderDao.updateOrder(orderId,10,null);
        return ServerResponse.createBySuccessMessage("取消订单成功");
    }

    @Override
    @Transactional
    public ServerResponse confimOrder(String orderId) {
        Optional<TbOrder> op = orderDao.findById(orderId);
        if (!op.isPresent()){
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),"订单参数错误");
        }
        orderDao.updateOrderState(orderId,20);
        return ServerResponse.createBySuccessMessage("确认配药成功");
    }

    @Override
    @Transactional
    public ServerResponse rejectOrder(String orderId,String msg) {
        TbUser user = getUser();
        Optional<TbOrder> op = orderDao.findById(orderId);
        if (!op.isPresent()){
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),"订单参数错误");
        }
        TbOrderReject reject = new TbOrderReject();
        reject.setMsg(msg);
        reject.setOrderId(orderId);
        reject.setUserId(user.getId());
        rejectDao.save(reject);
        orderDao.updateOrderState(orderId,10);
        return ServerResponse.createBySuccessMessage("驳回订单成功");
    }

    @Override
    public ServerResponse deliveryPullOrder(String orderId) {
        TbUser user = getUser();
        Optional<TbOrder> op = orderDao.findById(orderId);
        if (!op.isPresent()){
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),"订单参数错误");
        }
        // todo
        TbOrderShipping shipping = shippingDao.findByOrderId(orderId);
        if (shipping ==null){
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),"配送订单参数错误,领取失败");
        }
        orderDao.updateOrderState(orderId,30);
        shippingDao.updateDelivery(orderId,user.getId());
        return ServerResponse.createBySuccessMessage("领取订单成功");
    }

    @Override
    @Transactional
    public ServerResponse deliveredOrder(String orderId, String pic, String audio) {
        TbUser user = getUser();
        Optional<TbOrder> op = orderDao.findById(orderId);
        if (!op.isPresent()){
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),"订单参数错误");
        }
        TbOrderOther orderOther = new TbOrderOther();
        orderOther.setAudio(audio);
        orderOther.setUserId(user.getId());
        orderOther.setPic(pic);
        orderOther.setOrderId(orderId);
        orderOther.setId(UUID.randomUUID().toString());
        orderOtherDao.save(orderOther);
        orderDao.updateOrderState(orderId,40);
        return ServerResponse.createBySuccessMessage("订单配送完成");

    }

    @Override
    @Transactional
    public ServerResponse recycleFacility(String orderId) {
//        TbUser user = getUser();
        Optional<TbOrder> op = orderDao.findById(orderId);
        if (!op.isPresent()){
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),"订单参数错误");
        }
//        if (!user.getId().equals(order.ged())){
//            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),"参数错误,不是您的订单,您无法取消");
//        }
        List<TbFacilityLease> leaseList = leaseDao.findByOrderIdAndState(orderId,0);
        for (TbFacilityLease l:leaseList){
            leaseDao.updateStateById(l.getId(),10);
            facilityDao.updateState(l.getFacilityId(),0);
        }
        return ServerResponse.createBySuccessMessage("订单物资归还成功");
    }

    @Override
    public ServerResponse finishOrder(String orderId) {
        recycleFacility(orderId);
        orderDao.updateOrderState(orderId,50);
        return ServerResponse.createBySuccessMessage("订单财务核算完成");
    }

    private MedicineDto medicine2Dto(TbMedicine medicine){
        if (medicine == null){
            return null;
        }
        MedicineDto dto = new MedicineDto();
        dto.setManufacturer(medicine.getManufacturer());
        dto.setUnitType(medicine.getStandard());
        dto.setSpe(medicine.getMedicineName());
        return dto;
    }
    private FacilityDto facility2Dto(TbFacility facility){
        if (facility == null){
            return null;
        }
        FacilityDto dto = new FacilityDto();
        dto.setName(facility.getItem());
        dto.setSuid(facility.getSuid());
        dto.setUnittype(facility.getItemNo());
//        dto.setType(facility);
        return dto;
    }
    private TbUser getUser(){
        String username = SecurityUtils.getSubject().getPrincipal().toString();
        return  userDao.findbyUsername(username);
    }
}
